home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Leser 15 / Amiga Plus Leser CD 15.iso / Tools / Development / MosaicSRC / libwww2 / HTAAUtil.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-03-13  |  13.5 KB  |  536 lines

  1.  
  2. /* MODULE                            HTAAUtil.c
  3. **        COMMON PARTS OF ACCESS AUTHORIZATION MODULE
  4. **            FOR BOTH SERVER AND BROWSER
  5. **
  6. ** IMPORTANT:
  7. **    Routines in this module use dynamic allocation, but free
  8. **    automatically all the memory reserved by them.
  9. **
  10. **    Therefore the caller never has to (and never should)
  11. **    free() any object returned by these functions.
  12. **
  13. **    Therefore also all the strings returned by this package
  14. **    are only valid until the next call to the same function
  15. **    is made. This approach is selected, because of the nature
  16. **    of access authorization: no string returned by the package
  17. **    needs to be valid longer than until the next call.
  18. **
  19. **    This also makes it easy to plug the AA package in:
  20. **    you don't have to ponder whether to free() something
  21. **    here or is it done somewhere else (because it is always
  22. **    done somewhere else).
  23. **
  24. **    The strings that the package needs to store are copied
  25. **    so the original strings given as parameters to AA
  26. **    functions may be freed or modified with no side effects.
  27. **
  28. **    The AA package does not free() anything else than what
  29. **    it has itself allocated.
  30. **
  31. **    AA (Access Authorization) package means modules which
  32. **    names start with HTAA.
  33. **
  34. ** AUTHORS:
  35. **    AL    Ari Luotonen    luotonen@dxcern.cern.ch
  36. **
  37. ** HISTORY:
  38. **
  39. **
  40. ** BUGS:
  41. **
  42. **
  43. */
  44.  
  45. #include <string.h>
  46. #include "HTUtils.h"
  47. #include "tcp.h"    /* NETREAD() etc.    */
  48. #include "HTAAUtil.h"    /* Implemented here    */
  49. #include "HTAssoc.h"    /* Assoc list        */
  50.  
  51.  
  52. /* PUBLIC                        HTAAScheme_enum()
  53. **        TRANSLATE SCHEME NAME INTO
  54. **        A SCHEME ENUMERATION
  55. **
  56. ** ON ENTRY:
  57. **    name        is a string representing the scheme name.
  58. **
  59. ** ON EXIT:
  60. **    returns        the enumerated constant for that scheme.
  61. */
  62. PUBLIC HTAAScheme HTAAScheme_enum ARGS1(CONST char*, name)
  63. {
  64.     static char *upcased = NULL;
  65.     char *cur;
  66.  
  67.     if (!name) return HTAA_UNKNOWN;
  68.  
  69.     StrAllocCopy(upcased, name);
  70.     cur = upcased;
  71.     while (*cur) {
  72.     *cur = TOUPPER(*cur);
  73.     cur++;
  74.     }
  75.     
  76.     if (!strncmp(upcased, "NONE", 4))
  77.     return HTAA_NONE;
  78.     else if (!strncmp(upcased, "BASIC", 5))
  79.     return HTAA_BASIC;
  80.     else if (!strncmp(upcased, "PUBKEY", 6))
  81.     return HTAA_PUBKEY;
  82.     else if (!strncmp(upcased, "KERBEROSV4", 10))
  83.     return HTAA_KERBEROS_V4;
  84.     else if (!strncmp(upcased, "KERBEROSV5", 10))
  85.     return HTAA_KERBEROS_V5;
  86. #ifdef PEM_AUTH
  87.     else if (!strncmp(upcased, "PEM", 3))
  88.         return HTAA_PEM;
  89.     else if (!strncmp(upcased, "PGP", 3))
  90.         return HTAA_PGP;
  91. #endif /* PEM_AUTH */
  92.     else
  93.     return HTAA_UNKNOWN;
  94. }
  95.  
  96.  
  97. /* PUBLIC                        HTAAScheme_name()
  98. **            GET THE NAME OF A GIVEN SCHEME
  99. ** ON ENTRY:
  100. **    scheme        is one of the scheme enum values:
  101. **            HTAA_NONE, HTAA_BASIC, HTAA_PUBKEY, ...
  102. **
  103. ** ON EXIT:
  104. **    returns        the name of the scheme, i.e.
  105. **            "None", "Basic", "Pubkey", ...
  106. */
  107. PUBLIC char *HTAAScheme_name ARGS1(HTAAScheme, scheme)
  108. {
  109.     switch (scheme) {
  110.       case HTAA_NONE:        return "None";          break;
  111.       case HTAA_BASIC:        return "Basic";         break;
  112.       case HTAA_PUBKEY:        return "Pubkey";        break;
  113.       case HTAA_KERBEROS_V4:    return "KerberosV4";    break;
  114.       case HTAA_KERBEROS_V5:    return "KerberosV5";    break;
  115. #ifdef PEM_AUTH
  116.       case HTAA_PEM:            return "PEM";           break;
  117.       case HTAA_PGP:            return "PGP";           break;
  118. #endif /* PEM_AUTH */
  119.       case HTAA_UNKNOWN:    return "UNKNOWN";       break;
  120.       default:            return "THIS-IS-A-BUG";
  121.     }
  122. }
  123.  
  124.  
  125. /* PUBLIC                            HTAAMethod_enum()
  126. **        TRANSLATE METHOD NAME INTO AN ENUMERATED VALUE
  127. ** ON ENTRY:
  128. **    name        is the method name to translate.
  129. **
  130. ** ON EXIT:
  131. **    returns        HTAAMethod enumerated value corresponding
  132. **            to the given name.
  133. */
  134. PUBLIC HTAAMethod HTAAMethod_enum ARGS1(CONST char *, name)
  135. {
  136.     char tmp[MAX_METHODNAME_LEN+1];
  137.     CONST char *src = name;
  138.     char *dest = tmp;
  139.  
  140.     if (!name) return METHOD_UNKNOWN;
  141.  
  142.     while (*src) {
  143.     *dest = TOUPPER(*src);
  144.     dest++;
  145.     src++;
  146.     }
  147.     *dest = 0;
  148.  
  149.     if (0==strcmp(tmp, "GET"))
  150.     return METHOD_GET;
  151.     else if (0==strcmp(tmp, "PUT"))
  152.     return METHOD_PUT;
  153.     else
  154.     return METHOD_UNKNOWN;
  155. }
  156.  
  157.  
  158. /* PUBLIC                        HTAAMethod_name()
  159. **            GET THE NAME OF A GIVEN METHOD
  160. ** ON ENTRY:
  161. **    method        is one of the method enum values:
  162. **            METHOD_GET, METHOD_PUT, ...
  163. **
  164. ** ON EXIT:
  165. **    returns        the name of the scheme, i.e.
  166. **            "GET", "PUT", ...
  167. */
  168. PUBLIC char *HTAAMethod_name ARGS1(HTAAMethod, method)
  169. {
  170.     switch (method) {
  171.       case METHOD_GET:        return "GET";           break;
  172.       case METHOD_PUT:        return "PUT";           break;
  173.       case METHOD_UNKNOWN:    return "UNKNOWN";       break;
  174.       default:            return "THIS-IS-A-BUG";
  175.     }
  176. }
  177.  
  178.  
  179. /* PUBLIC                        HTAAMethod_inList()
  180. **        IS A METHOD IN A LIST OF METHOD NAMES
  181. ** ON ENTRY:
  182. **    method        is the method to look for.
  183. **    list        is a list of method names.
  184. **
  185. ** ON EXIT:
  186. **    returns        YES, if method was found.
  187. **            NO, if not found.
  188. */
  189. PUBLIC BOOL HTAAMethod_inList ARGS2(HTAAMethod,    method,
  190.                     HTList *,    list)
  191. {
  192.     HTList *cur = list;
  193.     char *item;
  194.  
  195.     while (NULL != (item = (char*)HTList_nextObject(cur))) {
  196.     if (TRACE) fprintf(stderr, " %s", item);
  197.     if (method == HTAAMethod_enum(item))
  198.         return YES;
  199.     }
  200.  
  201.     return NO;    /* Not found */
  202. }
  203.  
  204.  
  205.  
  206. /* PUBLIC                        HTAA_templateMatch()
  207. **        STRING COMPARISON FUNCTION FOR FILE NAMES
  208. **           WITH ONE WILDCARD * IN THE TEMPLATE
  209. ** NOTE:
  210. **    This is essentially the same code as in HTRules.c, but it
  211. **    cannot be used because it is embedded in between other code.
  212. **    (In fact, HTRules.c should use this routine, but then this
  213. **     routine would have to be more sophisticated... why is life
  214. **     sometimes so hard...)
  215. **
  216. ** ON ENTRY:
  217. **    template    is a template string to match the file name
  218. **            agaist, may contain a single wildcard
  219. **            character * which matches zero or more
  220. **            arbitrary characters.
  221. **    filename    is the filename (or pathname) to be matched
  222. **            agaist the template.
  223. **
  224. ** ON EXIT:
  225. **    returns        YES, if filename matches the template.
  226. **            NO, otherwise.
  227. */
  228. PUBLIC BOOL HTAA_templateMatch ARGS2(CONST char *, template, 
  229.                      CONST char *, filename)
  230. {
  231.     CONST char *p = template;
  232.     CONST char *q = filename;
  233.     int m;
  234.  
  235.     for( ; *p  &&  *q  &&  *p == *q; p++, q++)    /* Find first mismatch */
  236.     ; /* do nothing else */
  237.     
  238.     if (!*p && !*q)    return YES;    /* Equally long equal strings */
  239.     else if ('*' == *p) {        /* Wildcard */
  240.     p++;                /* Skip wildcard character */
  241.     m = strlen(q) - strlen(p);    /* Amount to match to wildcard */
  242.     if (m < 0) return NO;        /* No match, filename too short */
  243.     else {            /* Skip the matched characters and compare */
  244.         if (strcmp(p, q+m))    return NO;    /* Tail mismatch */
  245.         else                return YES;    /* Tail match */
  246.     }
  247.     }    /* if wildcard */
  248.     else        return NO;    /* Length or character mismatch */
  249. }
  250.  
  251.  
  252. /* PUBLIC                    HTAA_makeProtectionTemplate()
  253. **        CREATE A PROTECTION TEMPLATE FOR THE FILES
  254. **        IN THE SAME DIRECTORY AS THE GIVEN FILE
  255. **        (Used by server if there is no fancier way for
  256. **        it to tell the client, and by browser if server
  257. **        didn't send WWW-ProtectionTemplate: field)
  258. ** ON ENTRY:
  259. **    docname    is the document pathname (from URL).
  260. **
  261. ** ON EXIT:
  262. **    returns    a template matching docname, and other files
  263. **        files in that directory.
  264. **
  265. **        E.g.  /foo/bar/x.html  =>  /foo/bar/ *
  266. **                            ^
  267. **                Space only to prevent it from
  268. **                being a comment marker here,
  269. **                there really isn't any space.
  270. */
  271. PUBLIC char *HTAA_makeProtectionTemplate ARGS1(CONST char *, docname)
  272. {
  273.     char *template = NULL;
  274.     char *slash = NULL;
  275.  
  276.     if (docname) {
  277.     StrAllocCopy(template, docname);
  278.     slash = strrchr(template, '/');
  279.     if (slash) slash++;
  280.     else slash = template;
  281.     *slash = (char)0;
  282.     StrAllocCat(template, "*");
  283.     }
  284.     else StrAllocCopy(template, "*");
  285.  
  286.     if (TRACE) fprintf(stderr,
  287.                "make_template: made template `%s' for file `%s'\n",
  288.                template, docname);
  289.  
  290.     return template;
  291. }
  292.  
  293.  
  294.  
  295.  
  296. /*
  297. ** Skip leading whitespace from *s forward
  298. */
  299. #define SKIPWS(s) while (*s==' ' || *s=='\t') s++;
  300.  
  301. /*
  302. ** Kill trailing whitespace starting from *(s-1) backwords
  303. */
  304. #define KILLWS(s) {char *c=s-1; while (*c==' ' || *c=='\t') *(c--)=(char)0;}
  305.  
  306.  
  307. /* PUBLIC                        HTAA_parseArgList()
  308. **        PARSE AN ARGUMENT LIST GIVEN IN A HEADER FIELD
  309. ** ON ENTRY:
  310. **    str    is a comma-separated list:
  311. **
  312. **            item, item, item
  313. **        where
  314. **            item ::= value
  315. **                   | name=value
  316. **                   | name="value"
  317. **
  318. **        Leading and trailing whitespace is ignored
  319. **        everywhere except inside quotes, so the following
  320. **        examples are equal:
  321. **
  322. **            name=value,foo=bar
  323. **             name="value",foo="bar"
  324. **              name = value ,  foo = bar
  325. **               name = "value" ,  foo = "bar"
  326. **
  327. ** ON EXIT:
  328. **    returns    a list of name-value pairs (actually HTAssocList*).
  329. **        For items with no name, just value, the name is
  330. **        the number of order number of that item. E.g.
  331. **        "1" for the first, etc.
  332. */
  333. PUBLIC HTAssocList *HTAA_parseArgList ARGS1(char *, str)
  334. {
  335.     HTAssocList *assoc_list = HTAssocList_new();
  336.     char *cur = NULL;
  337.     char *name = NULL;
  338.     int index = 0;
  339.  
  340.     if (!str) return assoc_list;
  341.  
  342.     while (*str) {
  343.     SKIPWS(str);                /* Skip leading whitespace */
  344.     cur = str;
  345.     index++;
  346.  
  347.     while (*cur  &&  *cur != '='  &&  *cur != ',')
  348.         cur++;    /* Find end of name (or lonely value without a name) */
  349.     KILLWS(cur);    /* Kill trailing whitespace */
  350.  
  351.     if (*cur == '=') {            /* Name followed by a value */
  352.         *(cur++) = (char)0;            /* Terminate name */
  353.         StrAllocCopy(name, str);
  354.         SKIPWS(cur);            /* Skip WS leading the value */
  355.         str = cur;
  356.         if (*str == '"') {            /* Quoted value */
  357.         str++;
  358.         cur = str;
  359.         while (*cur  &&  *cur != '"') cur++;
  360.         if (*cur == '"')
  361.             *(cur++) = (char)0;    /* Terminate value */
  362.         /* else it is lacking terminating quote */
  363.         SKIPWS(cur);            /* Skip WS leading comma */
  364.         if (*cur == ',') cur++;        /* Skip separating colon */
  365.         }
  366.         else {                /* Unquoted value */
  367.         while (*cur  &&  *cur != ',') cur++;
  368.         KILLWS(cur);            /* Kill trailing whitespace */
  369.         if (*cur == ',')
  370.             *(cur++) = (char)0;
  371.         /* else *cur already NULL */
  372.         }
  373.     }
  374.     else {    /* No name, just a value */
  375.         if (*cur == ',') 
  376.         *(cur++) = (char)0;        /* Terminate value */
  377.         /* else last value on line (already terminated by NULL) */
  378.         StrAllocCopy(name, "nnn");    /* Room for item order number */
  379.         sprintf(name, "%d", index); /* Item order number for name */
  380.     }
  381.     HTAssocList_add(assoc_list, name, str);
  382.     str = cur;
  383.     } /* while *str */
  384.  
  385.     return assoc_list;
  386. }
  387.  
  388.  
  389.  
  390. /************** HEADER LINE READER -- DOES UNFOLDING *************************/
  391.  
  392. #define BUFFER_SIZE    16384
  393.  
  394. PRIVATE char buffer[BUFFER_SIZE + 1];
  395. PRIVATE char *start_pointer = buffer;
  396. PRIVATE char *end_pointer = buffer;
  397. PRIVATE int in_soc = -1;
  398.  
  399. /* PUBLIC                        HTAA_setupReader()
  400. **        SET UP HEADER LINE READER, i.e. give
  401. **        the already-read-but-not-yet-processed
  402. **        buffer of text to be read before more
  403. **        is read from the socket.
  404. ** ON ENTRY:
  405. **    start_of_headers is a pointer to a buffer containing
  406. **            the beginning of the header lines
  407. **            (rest will be read from a socket).
  408. **    length        is the number of valid characters in
  409. **            'start_of_headers' buffer.
  410. **    soc        is the socket to use when start_of_headers
  411. **            buffer is used up.
  412. ** ON EXIT:
  413. **    returns        nothing.
  414. **            Subsequent calls to HTAA_getUnfoldedLine()
  415. **            will use this buffer first and then
  416. **            proceed to read from socket.
  417. */
  418. PUBLIC void HTAA_setupReader ARGS3(char *,    start_of_headers,
  419.                    int,        length,
  420.                    int,        soc)
  421. {
  422.     start_pointer = buffer;
  423.     if (start_of_headers) {
  424.     strncpy(buffer, start_of_headers, length);
  425.     buffer[length] = (char)0;
  426.     end_pointer = buffer + length;
  427.     }
  428.     else {
  429.     *start_pointer = (char)0;
  430.     end_pointer = start_pointer;
  431.     }
  432.     in_soc = soc;
  433. }
  434.  
  435.  
  436. /* PUBLIC                        HTAA_getUnfoldedLine()
  437. **        READ AN UNFOLDED HEADER LINE FROM SOCKET
  438. ** ON ENTRY:
  439. **    HTAA_setupReader must absolutely be called before
  440. **    this function to set up internal buffer.
  441. **
  442. ** ON EXIT:
  443. **    returns    a newly-allocated character string representing
  444. **        the read line.  The line is unfolded, i.e.
  445. **        lines that begin with whitespace are appended
  446. **        to current line.  E.g.
  447. **
  448. **            Field-Name: Blaa-Blaa
  449. **             This-Is-A-Continuation-Line
  450. **             Here-Is_Another
  451. **
  452. **        is seen by the caller as:
  453. **
  454. **    Field-Name: Blaa-Blaa This-Is-A-Continuation-Line Here-Is_Another
  455. **
  456. */
  457. PUBLIC char *HTAA_getUnfoldedLine NOARGS
  458. {
  459.     char *line = NULL;
  460.     char *cur;
  461.     int count;
  462.     BOOL peek_for_folding = NO;
  463.  
  464.     if (in_soc < 0) {
  465.     fprintf(stderr, "%s %s\n",
  466.         "HTAA_getUnfoldedLine: buffer not initialized",
  467.         "with function HTAA_setupReader()");
  468.     return NULL;
  469.     }
  470.  
  471.     for(;;) {
  472.  
  473.     /* Reading from socket */
  474.  
  475.     if (start_pointer >= end_pointer) {/*Read the next block and continue*/
  476.         count = NETREAD(in_soc, buffer, BUFFER_SIZE);
  477.         if (count <= 0) {
  478.         in_soc = -1;
  479.         return line;
  480.         }
  481.         start_pointer = buffer;
  482.         end_pointer = buffer + count;
  483.         *end_pointer = (char)0;
  484. #ifdef NOT_ASCII
  485.         cur = start_pointer;
  486.         while (cur < end_pointer) {
  487.         *cur = TOASCII(*cur);
  488.         cur++;
  489.         }
  490. #endif /*NOT_ASCII*/
  491.     }
  492.     cur = start_pointer;
  493.  
  494.  
  495.     /* Unfolding */
  496.     
  497.     if (peek_for_folding) {
  498.         if (*cur != ' '  &&  *cur != '\t')
  499.         return line;    /* Ok, no continuation line */
  500.         else        /* So this is a continuation line, continue */
  501.         peek_for_folding = NO;
  502.     }
  503.  
  504.  
  505.     /* Finding end-of-line */
  506.  
  507.     while (cur < end_pointer && *cur != '\n') /* Find the end-of-line */
  508.         cur++;                  /* (or end-of-buffer).  */
  509.  
  510.     
  511.     /* Terminating line */
  512.  
  513.     if (cur < end_pointer) {    /* So *cur==LF, terminate line */
  514.         *cur = (char)0;        /* Overwrite LF */
  515.         if (*(cur-1) == '\r')
  516.         *(cur-1) = (char)0;    /* Overwrite CR */
  517.         peek_for_folding = YES;    /* Check for a continuation line */
  518.     }
  519.  
  520.  
  521.     /* Copying the result */
  522.  
  523.     if (line)
  524.         StrAllocCat(line, start_pointer);    /* Append */
  525.     else
  526.         StrAllocCopy(line, start_pointer);    /* A new line */
  527.  
  528.     start_pointer = cur+1;    /* Skip the read line */
  529.  
  530.     } /* forever */
  531. }
  532.  
  533.  
  534.  
  535.  
  536.